package cn.edu.xmut.chen.zhlg.zhlg.message.service.impl;

import cn.edu.xmut.chen.zhlg.common.HttpResult.Result;
import cn.edu.xmut.chen.zhlg.zhlg.message.entity.PrivateChat;
import cn.edu.xmut.chen.zhlg.zhlg.message.entity.PrivateMessage;
import cn.edu.xmut.chen.zhlg.zhlg.message.mapper.PrivateChatMapper;
import cn.edu.xmut.chen.zhlg.zhlg.message.mapper.PrivateMessageMapper;
import cn.edu.xmut.chen.zhlg.zhlg.message.param.MessageQueryParam;
import cn.edu.xmut.chen.zhlg.zhlg.message.param.MessageSendParam;
import cn.edu.xmut.chen.zhlg.zhlg.message.result.ChatResult;
import cn.edu.xmut.chen.zhlg.zhlg.message.result.MessageResult;
import cn.edu.xmut.chen.zhlg.zhlg.message.service.ChatService;
import cn.edu.xmut.chen.zhlg.zhlg.user.entity.User;
import cn.edu.xmut.chen.zhlg.zhlg.user.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {
    private static final Logger log = LoggerFactory.getLogger(ChatServiceImpl.class);
    private final PrivateChatMapper chatMapper;
    private final PrivateMessageMapper messageMapper;
    private final UserMapper userMapper;

    @Override
    public PrivateChat getOrCreatePrivateChat(String userId1, String userId2) {
        String user1Id = userId1.compareTo(userId2) < 0 ? userId1 : userId2;
        String user2Id = userId1.compareTo(userId2) < 0 ? userId2 : userId1;
        
        PrivateChat chat = chatMapper.selectByUserPair(user1Id, user2Id);
        if (chat != null) {
            return chat;
        }

        PrivateChat newChat = new PrivateChat();
        newChat.setId(user1Id + '_' + user2Id);
        newChat.setUser1Id(user1Id);
        newChat.setUser2Id(user2Id);
        newChat.setCreateTime(new Date());
        
        chatMapper.insert(newChat);
        return newChat;
    }

    @Override
    public MessageResult sendMessage(MessageSendParam param) {
        // 验证参数
        if(param.getSenderId() == null || param.getReceiverId() == null) {
            throw new IllegalArgumentException("发送者和接收者ID不能为空");
        }

        PrivateChat chat = getOrCreatePrivateChat(param.getSenderId(), param.getReceiverId());

        String messageId = "msg_" + UUID.randomUUID();
        PrivateMessage message = new PrivateMessage();
        message.setId(messageId);
        message.setChatId(chat.getId());
        message.setSenderId(param.getSenderId());
        message.setReceiverId(param.getReceiverId());
        message.setContentType(param.getContentType());
        message.setContent(param.getContent());
        message.setCreateTime(new Date());
        message.setIsRead(false);

        messageMapper.insert(message);
        chatMapper.updateLastMessage(chat.getId(), messageId, new Date());

        return convertToResult(message);
    }

    @Override
    public List<MessageResult> getMessages(MessageQueryParam param) {
        log.info("【消息查询】开始查询消息，会话ID: {}, 用户ID: {}, 页码: {}, 每页数量: {}",param.getChatId(), param.getCurrentUserId(), param.getPageNum(), param.getPageSize());
        int offset = (param.getPageNum() - 1) * param.getPageSize();
        // 修改为使用带用户ID的查询
        return messageMapper.selectVisibleByChatId(
                        param.getChatId(),
                        param.getCurrentUserId(), // 需要在前端传入当前用户ID
                        offset,
                        param.getPageSize())
                .stream()
                .map(this::convertToResult)
                .collect(Collectors.toList());
    }

    @Override
    public Result deleteChat(MessageQueryParam param) {
        String chatId = param.getChatId();
        String userId = param.getCurrentUserId(); // 需要在前端传入当前用户ID

        // 修改为标记删除而不是物理删除
        int count = messageMapper.markDeletedByUser(chatId, userId);
        if(count > 0) {
            return Result.success("已从你的聊天记录中删除");
        }
        return Result.fail("删除失败");
    }

    @Override
    public List<ChatResult> getMessageList(String userId, Integer pageNum, Integer pageSize) {
        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;

        return chatMapper.selectByUserIdWithLimit(
                        userId,
                        offset,
                        pageSize)
                .stream()
                .map(chat -> convertToChatResult(chat, userId))
                .collect(Collectors.toList());
    }

    private ChatResult convertToChatResult(PrivateChat chat,String userId) {
        log.info("【会话查询】开始查询会话，用户ID: {}, chat: {}",userId, chat);
        ChatResult result = new ChatResult();
        String chatId = chat.getId();
        PrivateMessage message = messageMapper.selectById(chatId);
        if(message == null)
            return result;

        String otherId = message.getSenderId().equals(userId) ? message.getReceiverId() : message.getSenderId();
        String lastMessage = message.getContent();
        if((userId.equals(message.getSenderId()) && message.getDeletedBySender())||
                (userId.equals(message.getReceiverId()) && message.getDeletedByReceiver())
        )
            lastMessage = "";


        result.setId(chatId);
        result.setLastMessage(lastMessage);
        result.setLastMessageTime(message.getCreateTime());
        result.setOtherUserId(otherId);
        result.setOtherUserNickname(userMapper.selectById(otherId).getNickName());
        result.setOtherPic(userMapper.selectById(otherId).getPic());
        return result;
    }

    private MessageResult convertToResult(PrivateMessage message) {
        MessageResult result = new MessageResult();
        result.setId(message.getId());
        result.setChatId(message.getChatId());
        result.setSenderId(message.getSenderId());
        result.setReceiverId(message.getReceiverId());
        result.setContentType(message.getContentType());
        result.setContent(message.getContent());
        result.setCreateTime(message.getCreateTime());
        result.setIsRead(message.getIsRead());
        return result;
    }


}